package com.info.zhiduoduo.admin.service;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.mapper.Condition;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.info.zhiduoduo.admin.listener.UploadEntrustProjectListener;
import com.info.zhiduoduo.admin.model.formbean.crowdsource.UploadProjectFileUrlFormBean;
import com.info.zhiduoduo.admin.model.formbean.entrust.*;
import com.info.zhiduoduo.alipay.constant.AlipayAgreementStatusEnum;
import com.info.zhiduoduo.alipay.constant.AlipayPrincipalEnum;
import com.info.zhiduoduo.common.configs.CommonConfig;
import com.info.zhiduoduo.common.configs.DocConfig;
import com.info.zhiduoduo.common.configs.NotificationConfig;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.company.CompanyAccountFlowAccountType;
import com.info.zhiduoduo.common.constants.company.CompanyAccountFlowBizType;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceRegfromType;
import com.info.zhiduoduo.common.constants.entrustmentproject.EntrustProjectImportState;
import com.info.zhiduoduo.common.constants.entrustmentproject.EntrustProjectImportType;
import com.info.zhiduoduo.common.constants.entrustmentproject.EntrustProjectState;
import com.info.zhiduoduo.common.constants.entrustmentproject.EntrustState;
import com.info.zhiduoduo.common.constants.maker.StudioState;
import com.info.zhiduoduo.common.constants.pay.PayTypeSn;
import com.info.zhiduoduo.common.constants.project.CalcAmountType;
import com.info.zhiduoduo.common.constants.project.ProjectType;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.RollbackException;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.formbean.BaseSimpleFormBean;
import com.info.zhiduoduo.common.utils.DateUtil;
import com.info.zhiduoduo.common.utils.EasyExcelUtil;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.formbean.crowdsource.AddCrowdsourceModel;
import com.info.zhiduoduo.core.formbean.entrustmentproject.ImportEntrustProjectFormBean;
import com.info.zhiduoduo.core.service.*;
import com.info.zhiduoduo.core.service.common.DocService;
import com.info.zhiduoduo.core.vo.entrustmentproject.ImportResultVO;
import com.info.zhiduoduo.repository.dto.entrustmentproject.*;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.dto.project.SameProjectDto;
import com.info.zhiduoduo.repository.dto.quota.ZhiduoduoCityQuotaDto;
import com.info.zhiduoduo.repository.entity.company.Company;
import com.info.zhiduoduo.repository.entity.company.CompanyAccountflow;
import com.info.zhiduoduo.repository.entity.company.CompanyPayment;
import com.info.zhiduoduo.repository.entity.crowdsource.Crowdsource;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceAccount;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProject;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProjectItem;
import com.info.zhiduoduo.repository.entity.maker.*;
import com.info.zhiduoduo.repository.entity.pay.Payment;
import com.info.zhiduoduo.repository.mapper.company.CompanyAccountMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyPaymentMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceAccountMapper;
import com.info.zhiduoduo.repository.mapper.entrustmentproject.EntrustmentProjectItemMapper;
import com.info.zhiduoduo.repository.mapper.entrustmentproject.EntrustmentProjectMapper;
import com.info.zhiduoduo.repository.mapper.maker.*;

import com.info.zhiduoduo.repository.mapper.quota.ZhiduoduoCityQuotaMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class EntrustProjectService {

	@Autowired
	CoreCrowdsourceService coreCrowdsourceService;
	@Autowired
	MakerAliPayService makerAliPayService;
	@Autowired
	CoreEntrustProjectServcie coreEntrustProjectServcie;
	@Autowired
	CoreInvoiceService coreInvoiceService;
	@Autowired
	MakerService makerService;
	@Autowired
	DocService docService;
	@Autowired
	CommonService commonService;
	@Autowired
	CoreMakerAlipayService coreMakerAlipayService;
	@Autowired
	CoreProjectService coreProjectService;

	@Resource
	EntrustmentProjectMapper entrustmentProjectMapper;
	@Resource
	CrowdsourceAccountMapper crowdsourceAccountMapper;
	@Resource
	EntrustmentProjectItemMapper entrustmentProjectItemMapper;
	@Resource
	ZhiduoduoCityQuotaMapper zhiduoduoCityQuotaMapper;
	@Resource
	MakerAlipayAgreementMapper makerAlipayAgreementMapper;
	@Resource
	MakerAlipayAccountBookMapper makerAlipayAccountBookMapper;
	@Resource
	MakerRescissionApplyMapper makerRescissionApplyMapper;
	@Resource
	CompanyAccountMapper companyAccountMapper;
	@Resource
	CompanyPaymentMapper companyPaymentMapper;
	@Resource
	MakerStudioMapper makerStudioMapper;
	@Resource
	CommonConfig commonConfig;
	@Resource
	CompanyMapper companyMapper;

	@Autowired
	DocConfig docConfig;
	@Autowired
	NotificationConfig notificationConfig;

	private ExecutorService executor = Executors.newSingleThreadExecutor();

	public SmartResult<EntrustmentProjectDto> listProjects(BaseSimpleFormBean<ListEntrustmentProjectFormBean> formBean) {
		@Valid ListEntrustmentProjectFormBean reqdata = formBean.getReqdata();
		Page<EntrustmentProjectDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		entrustmentProjectMapper.listProjects(reqdata.getName(), reqdata.getProjectType(), reqdata.getFrom(), reqdata.getTo(),0, reqdata.getWhetherUploadFile());
		return SmartResult.ofPage(page);
	}

	@Transactional
	public SmartResult<ImportResultVO> importProjects(MultipartFile file, ImportEntrustProjectsFormBean formBean, int projectType) {
		String fileName = file.getOriginalFilename();
		Double serviceRate = formBean.getServiceRate();
		int payId = formBean.getPayId();
		Integer partyId = formBean.getPartyId();
		Integer isCheckBankCard = formBean.getIsCheckBankCard();
		Integer actualCompanyId = formBean.getActualCompanyId();
		Payment payment = new Payment().selectById(payId);
		Asserts.notNull(payment, StatusMsg.StatusMsg_101);

		EntrustmentProject entrustmentProject = new EntrustmentProject().setOriginFileName(fileName)
																		.setImportedServiceRate(serviceRate)
																		.setPayId(payId)
																		.setPrincipalId(payment.getSourceId())
																		.setPartyId(partyId)
																		.setProjectType(projectType)
																		.setActualCompanyId(actualCompanyId)
																		.setRemark(formBean.getRemark())
																		.setImportType(EntrustProjectImportType.ADMIN_BACKEND);
		try {
			//读取文件
			UploadEntrustProjectListener listener = new UploadEntrustProjectListener(entrustmentProject, isCheckBankCard, coreCrowdsourceService, coreEntrustProjectServcie);
			EasyExcel.read(file.getInputStream(), ImportEntrustProjectFormBean.class, listener).sheet().headRowNumber(6).doRead();

			// 保存上传的文件
			String newFileName = DateUtil.getString(new Date(), DateUtil.FORMAT_STYLE_5) + File.separator
					+ StringUtils.joinWith("_", listener.getEntrustmentProject().getId(), listener.getCompany().getCompid(), fileName);
			File newFile = new File(docConfig.getEntrustmentProjectFilePath(), newFileName);
			FileUtils.writeByteArrayToFile(newFile, file.getBytes());
			//修改文件路径
			if(listener.getEntrustmentProject().getId() != null) {
				listener.getEntrustmentProject().setFilePathName(newFileName).updateById();
			}

			return listener.getSmartResult();
		} catch (Exception e) {
			log.error("导入委托接单项目失败", e);
			//手动回滚
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return SmartResult.fail(StatusMsg.StatusMsg_135, e.getMessage());
		}
	}

	public ResponseEntity<?> downloadHistoryProjectFile(int importId) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(importId);
		if (entrustmentProject == null) {
			return ResponseEntity.notFound().build();
		}
		try {
			FileInputStream fis = new FileInputStream(
					new File(docConfig.getEntrustmentProjectFilePath(), entrustmentProject.getFilePathName()));
			return ResponseEntity.ok()
					.contentType(MediaType.valueOf("application/force-download"))
					.header("Content-Disposition",
							"attachment;filename=" + URLEncoder.encode(entrustmentProject.getOriginFileName(), "utf-8"))
					.body(new InputStreamResource(fis));
		} catch (Exception e) {
			return ResponseEntity.notFound().build();
		}
	}

	public SmartResult editProjectItem(BaseSimpleFormBean<EditProjectItemFormBean> formBean) {
		@Valid EditProjectItemFormBean reqdata = formBean.getReqdata();
		EntrustmentProjectItem item = new EntrustmentProjectItem().selectById(reqdata.getId());
		Asserts.notNull(item, StatusMsg.StatusMSG_1101);
		Asserts.isTrue(NumberUtil.intIn(item.getState(), EntrustProjectState.CREATED, EntrustProjectState.FAIL), StatusMsg.StatusMsg_1107);
		Asserts.isTrue(NumberUtil.intIn(item.getEntrustState(), EntrustState.CREATED, EntrustState.RECEIVED), StatusMsg.StatusMsg_1107);

		BeanUtils.copyProperties(reqdata, item);
		Integer entrusteeId = reqdata.getEntrusteeId();
		if (NumberUtil.safeInt(entrusteeId) > 0) {
			MakerDetailDto maker = makerService.getUserInfo(entrusteeId);
			if (maker != null) item.setEntrusteeName(maker.getRealname()).setEntrusteeStudio(maker.getUsername());
		}

		// 判断自然人是否存在, 不存在则新建
		CrowdsourceAccount crowdsourceAccount = crowdsourceAccountMapper.findByIdno(item.getPayeeIdNo(), item.getPayeeName());
		if (crowdsourceAccount == null) {
			int regfrom = CrowdsourceRegfromType.ENTRUSTMENT_PROJECT;
			if (ProjectType.isEntrustProject(item.getProjectType())) {
				regfrom = CrowdsourceRegfromType.MAKERGROUP_PROJECT;
			}
			AddCrowdsourceModel model = new AddCrowdsourceModel().setIdno(item.getPayeeIdNo())
					.setPhone(item.getPhone())
					.setRealname(item.getPayeeName())
					.setBindcompid(item.getCompid())
					.setRegfrom(regfrom);
			if (item.getAccountType() == 2) {
				model.setAcctno(item.getAccountNo());
			} else if (item.getAccountType() == 1) {
				model.setAlipayLogonId(item.getAccountNo());
			}
			Crowdsource crowdsource = coreCrowdsourceService.addCrowdsource(model);
			item.setCrowdsourceid(crowdsource.getCrowdsourceid()).setCrowdsourceName(item.getPayeeName());
		} else {
			new Crowdsource().setCrowdsourceid(crowdsourceAccount.getCrowdsourceid()).setPhone(item.getPhone()).updateById();
			crowdsourceAccount.setIdno(item.getPayeeIdNo()).setRealname(item.getPayeeName()).setBindcompid(item.getCompid());
			if (item.getAccountType() == 2) {
				crowdsourceAccount.setAcctno(item.getAccountNo());
			} else if (item.getAccountType() == 1) {
				crowdsourceAccount.setAlipayLogonId(item.getAccountNo());
			}
			crowdsourceAccount.updateById();
			item.setCrowdsourceid(crowdsourceAccount.getCrowdsourceid()).setCrowdsourceName(crowdsourceAccount.getRealname());
		}

		// 重新计算item Amount
		Company company = companyMapper.selectById(item.getCompid());
		coreEntrustProjectServcie.calculateItemAmount(item, company, item.getServiceRate(), item.getProjectType());
		if (item.updateById()) {
			EntrustmentProject entrustmentProject = entrustmentProjectMapper.selectById(item.getImportId());
			coreEntrustProjectServcie.calcProjectTotalAmount(entrustmentProject);
			entrustmentProject.updateById();
			return SmartResult.success();
		}

		return SmartResult.fail();
	}

	public SmartResult<EntrustmentProjectItemDto> listProjectItems(BaseSimpleFormBean<ListEntrustmentProjectItemFormBean> formBean) {
		@Valid ListEntrustmentProjectItemFormBean reqdata = formBean.getReqdata();
		Page<EntrustmentProjectItemDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		int payState = reqdata.getPayState();
		int state = 0;
		if (payState == 1) {
			state = EntrustProjectState.FINISH;
		} else if (payState == 2) {
			state = EntrustProjectState.FAIL;
		}
		entrustmentProjectItemMapper.list(reqdata.getImportId(), reqdata.getName(), reqdata.getFrom(), reqdata.getTo(), state);
		return SmartResult.ofPage(page);
	}

	public void exportProjectItems(HttpServletResponse response, int importId, String name, Date from, Date to, int state) {
		int payState = state;
		if (payState == 1) {
			state = EntrustProjectState.FINISH;
		} else if (payState == 2) {
			state = EntrustProjectState.FAIL;
		}
		List<EntrustmentProjectItemExportVO> voList = entrustmentProjectItemMapper.list(importId, name, from, to, state)
				.stream()
				.map(EntrustmentProjectItemExportVO::of)
				.collect(Collectors.toList());

		EasyExcelUtil.download(response, "委托子项目列表", EntrustmentProjectItemExportVO.class, voList);
	}

	public SmartResult submit(BaseSimpleFormBean<Integer> formBean) {
		@Valid Integer importId = formBean.getReqdata();
		EntrustmentProject project = new EntrustmentProject().selectById(importId);
		Asserts.notNull(project);

		Asserts.equals(project.getState(), EntrustProjectImportState.CREATED, StatusMsg.StatusMsg_1102);
		project.setState(EntrustProjectImportState.SUBMITTED).updateById();
		return SmartResult.success();
	}

	@Transactional
	public SmartResult dispatchEntrustees(BaseSimpleFormBean<DispatchEntrusteeFormBean> formBean) {
		@Valid DispatchEntrusteeFormBean reqdata = formBean.getReqdata();
		List<DispatchEntrusteeFormBean.ProjectUserId> idList = reqdata.getProjectUserIdList();
		if (CollectionUtils.isEmpty(idList)) return SmartResult.ofErrorParam();

		int payId = reqdata.getPayId();
		Integer partyId = reqdata.getPartyId();
		Payment payment = new Payment().selectById(payId);
		if (payment == null || !PayTypeSn.ZFB_WTJD.equals(payment.getPayTypeSn())) {
			return SmartResult.fail(StatusMsg.StatusMsg_456);
		}
		// 验证手机验证码
		commonService.checkPhoneVerifyCode(notificationConfig.getBossPhone(), reqdata.getVerifyCode());

		// 校验选择的受托人是否都有效
		AlipayPrincipalEnum isvEnum = makerAliPayService.getISVPrincipal();
		int isvId = isvEnum.id;
		int dispatchPrincipalId = payment.getSourceId();
		for (DispatchEntrusteeFormBean.ProjectUserId bean : idList) {
			int userid = bean.getUserid();
			MakerDetailDto maker = makerService.getUserInfo(userid);
			// 限制天津未开户创客，限制已注销或申请注销已受理的创客进行交易
			if (NumberUtil.equals(maker.getOpeningLocation(), 1) && maker.getStudioState() != StudioState.CONFIRMED) {
				return SmartResult.fail(StatusMsg.StatusMsg_204).setObject(bean);
			}
			if (NumberUtil.equals(maker.getState(), Constants.user_state_4)) {
				return SmartResult.fail(StatusMsg.StatusMsg_231).setObject(bean);
			}
			MakerRescissionApply rescissionApply = makerRescissionApplyMapper.getByUserid(userid);
			if (rescissionApply != null && NumberUtil.equals(rescissionApply.getState(), 2)) {
				return SmartResult.fail(StatusMsg.StatusMsg_231).setObject(bean);
			}
			MakerAlipayAgreement alipayAgreement = makerAlipayAgreementMapper.getByIsvIdAndUserid(isvId, userid);
			MakerAlipayAccountBook alipayAccountBook = makerAlipayAccountBookMapper.getByIsvIdAndUserid(isvId, userid);
			if (alipayAgreement == null || !NumberUtil.equals(alipayAgreement.getStatus(), AlipayAgreementStatusEnum.NORMAL.id)) {
				return SmartResult.fail(StatusMsg.StatusMsg_233).setObject(bean);
			}
			if (alipayAccountBook == null) {
				return SmartResult.fail(StatusMsg.StatusMsg_235).setObject(bean);
			}
		}
		// 获取选择的项目列表
		List<EntrustmentProjectItem> list = idList.stream().map(bean -> {
			MakerDetailDto userInfo = makerService.getUserInfo(bean.getUserid());
			EntrustmentProjectItem projectItem = new EntrustmentProjectItem().selectById(bean.getProjectId());
			if (projectItem == null) return null;
			return projectItem.setEntrusteeId(bean.getUserid())
					.setEntrusteeName(userInfo.getRealname())
					.setEntrusteeStudio(userInfo.getUsername())
					.setEntrusteeIdno(userInfo.getIdno())
					.setPrincipalId(dispatchPrincipalId);
		}).filter(Objects::nonNull).collect(Collectors.toList());
		// 检查项目是否已经提交
		for (EntrustmentProjectItem item : list) {
			EntrustmentProject project = new EntrustmentProject().selectById(item.getImportId());
			if (project == null) {
				return SmartResult.fail(StatusMsg.StatusMSG_1101).setObject(project);
			}
			if (project.getState() != EntrustProjectImportState.SUBMITTED) {
				return SmartResult.fail(StatusMsg.StatusMsg_1104).setObject(project);
			}
			project.setPrincipalId(dispatchPrincipalId).setPartyId(partyId).setPayId(payId).updateById();
		}
		//校验余额是否足够,判断限额,生成流水
		EntrustmentProject project = new EntrustmentProject().selectById(list.get(0).getImportId());
		deductCompanyBalance(project, list);
		//委托发单总金额
		coreEntrustProjectServcie.processProjectPrincipalTransfer2Trustee(list);
		return SmartResult.success();
	}

	/**
	 * 校验创客团余额是否足够
	 */
	public void deductCompanyBalance(EntrustmentProject project, List<EntrustmentProjectItem> list) {
		int compid = project.getCompid();
		Integer payId = project.getPayId();
		CompanyPayment companyPayment = companyPaymentMapper.getCompanyPayment(compid, payId);
		Asserts.notNull(companyPayment, StatusMsg.StatusMsg_365);
		//委托项目总含税金额
		BigDecimal totalAmount = list.stream().map(EntrustmentProjectItem::getTaxInclusiveAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
		//判断余额是否足够,误差为10可以发单
		BigDecimal makerGrouponBalance = companyPayment.getBalance();
		if(makerGrouponBalance.subtract(totalAmount).compareTo(new BigDecimal(-10)) < 0){
			throw new SmartException(StatusMsg.StatusMsg_365);
		}

		Map<Integer, List<EntrustmentProjectItem>> map = list.stream().collect(Collectors.groupingBy(EntrustmentProjectItem::getEntrusteeId));
		for (Integer entrusteeId : map.keySet()) {
			EntrustmentProjectItem item = map.get(entrusteeId).get(0);
			BigDecimal userTotalAmount = list.stream().map(EntrustmentProjectItem::getTaxInclusiveAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);

			// 增加判断创客注册地年度限额
			ZhiduoduoCityQuotaDto cityQuota = zhiduoduoCityQuotaMapper.getByMakerId(entrusteeId);
			if (cityQuota != null) {
				double cityYearQuotaTotalAmount = coreProjectService.getUserYearlyTotalAmount(entrusteeId, CalcAmountType.PROCESSING).add(userTotalAmount).doubleValue();
				if(cityYearQuotaTotalAmount > NumberUtil.safeDouble(cityQuota.getYearlyQuota())) {
					throw SmartException.of(StatusMsg.StatusMsg_273.getState(), "委托创客：【" + item.getEntrusteeName() + "】" + StatusMsg.StatusMsg_273.getMsg());
				}
			}

			// 判断个人所有业务限额
			BigDecimal userIdnoYearAmout = userTotalAmount.add(coreProjectService.getTotalAmountByUserIdno(item.getEntrusteeIdno(), 0, item.getProjectType(), CalcAmountType.CHECKED, 0));
			BigDecimal userIdnoTwelveMonthAmout = userTotalAmount.add(coreProjectService.getTotalAmountByUserIdno(item.getEntrusteeIdno(), 0, item.getProjectType(), CalcAmountType.CHECKED, 1));

			// 个人所有业务年度限额 项目： 、智众包、纯代理、智零工、委托接单、创客团
			boolean e1 = userIdnoYearAmout.add(userTotalAmount).compareTo(commonConfig.getUserIdnoYearQuota()) <= 0;
			if (!e1) {
				throw SmartException.of(StatusMsg.StatusMsg_271.getState(), "委托创客：【" + item.getEntrusteeName() + "】" + StatusMsg.StatusMsg_271.getMsg());
			}
			// 个人所有业务12个月限额
			boolean e2 = userIdnoTwelveMonthAmout.add(userTotalAmount).compareTo(commonConfig.getUserIdnoYearQuota()) <= 0;
			if (!e2) {
				throw SmartException.of(StatusMsg.StatusMsg_272.getState(), "委托创客：【" + item.getEntrusteeName() + "】" + StatusMsg.StatusMsg_272.getMsg());
			}
		}

		for (EntrustmentProjectItem item : list) {
			// 支付金额
			BigDecimal payAmount = item.getTaxInclusiveAmount();

			// 扣除企业的创客团余额
			BigDecimal beforeBalance = companyPayment.getBalance();
			BigDecimal currBalance = beforeBalance.subtract(payAmount);
			companyPayment.setBalance(currBalance);
			Asserts.isTrue(companyPayment.updateById(), StatusMsg.StatusMsg_199);

			// 生成企业流水记录
			String flowname = "委托接单企业支付项目款";
			CompanyAccountflow accountflow = new CompanyAccountflow().setCompid(compid)
																	 .setPayId(companyPayment.getPayId())
																	 .setFlowname(flowname)
																	 .setFlowtype(2)
																	 .setBizid(project.getId())
																	 .setItemId(item.getId())
																	 .setBizType(CompanyAccountFlowBizType.ENTRUST_PROJECT)
																	 .setAccountType(CompanyAccountFlowAccountType.MAKER_GROUPON)
																	 .setFlowAmount(payAmount)
																	 .setBeforeBalance(beforeBalance)
																	 .setBeforeFrozenBalance(companyPayment.getFrozenBalance())
																	 .setCurrBalance(currBalance)
																	 .setCurrFrozenBalance(companyPayment.getFrozenBalance());
			if (!accountflow.insert()) {
				throw new RollbackException("生成支付流水失败");
			}
		}
	}

	public SmartResult removeProject(BaseSimpleFormBean<Integer> formBean) {
		@Valid Integer importId = formBean.getReqdata();
		EntrustmentProject project = new EntrustmentProject().selectById(importId);
		if (project.getImportType() == EntrustProjectImportType.ADMIN_BACKEND) {
			// 管理后台, 必须是新建和已提交的状态, 否则不能删除
			Asserts.isTrue(NumberUtil.intIn(project.getState(), EntrustProjectImportState.CREATED, EntrustProjectImportState.SUBMITTED),
					StatusMsg.StatusMsg_1102);
		} else if (project.getImportType() == EntrustProjectImportType.COMPANY_BACKEND) {
			Asserts.equals(project.getState(), EntrustProjectImportState.CREATED, StatusMsg.StatusMsg_1102);
		} else {
			return SmartResult.ofOptFail();
		}
		project.deleteById();
		entrustmentProjectItemMapper.deleteByImportId(importId);
		return SmartResult.success();
	}

	public SmartResult removeProjectItems(BaseSimpleFormBean<String> formBean) {
		List<Integer> idList = StringUtil.splitToInt(formBean.getReqdata(), ",");
		List<Integer> errorIds = idList.stream()
				.distinct()
				.map(id -> new EntrustmentProjectItem().selectById(id))
				.filter(item -> !NumberUtil.equals(item.getState(), EntrustProjectState.CREATED))
				.map(EntrustmentProjectItem::getId)
				.collect(Collectors.toList());
		if (CollectionUtils.isNotEmpty(errorIds)) {
			return SmartResult.fail(StatusMsg.StatusMsg_1103).setList(errorIds);
		}
		if (CollectionUtils.isNotEmpty(idList)) {
			entrustmentProjectItemMapper.deleteBatchIds(idList);
		}
		return SmartResult.success();
	}

	/**
	 * 查询上一次企业发单项目的创客
	 *
	 * @param compId
	 * @return
	 */
	public SmartResult<EntrustmentProjectMakerDto> queryLastProjectMaker(Integer compId) {
		Asserts.notNull(compId, StatusMsg.StatusMsg_133);
		List<EntrustmentProjectMakerDto> makerDtoList = entrustmentProjectItemMapper.queryLastProjectMaker(compId);
		return SmartResult.success(makerDtoList);
	}

	public void downloadEntrustProjectContract(HttpServletResponse response, int projectItemId) {
		docService.downloadEntrustProjectContract(response, projectItemId);
	}

	public SmartResult editProjectItemAfterSubmit(BaseSimpleFormBean<EditProjectItemAfterSubmitFormBean> formBean) {
		@Valid EditProjectItemAfterSubmitFormBean reqdata = formBean.getReqdata();
		List<EntrustmentProjectItem> itemList = new EntrustmentProjectItem().selectList(Condition.create().in("id", reqdata.getIds()));
		itemList.stream().forEach(item -> {
			String name = reqdata.getName();
			Integer categoryid = reqdata.getCategoryid();
			String invoiceContent = reqdata.getInvoiceContent();
			item.setName(name).setContent(reqdata.getContent()).setInvoiceContent(invoiceContent).setCategoryid(categoryid).updateById();
		});

		return SmartResult.success();
	}

	/**
	 * 获取企业历史委托接单列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult<EntrustmentProjectCompanyDto> queryCompanyHistoryProjects(BaseSimpleFormBean<Integer> formBean) {
		Integer compId = formBean.getReqdata();
		Asserts.notNull(compId, StatusMsg.StatusMsg_133);

		Page<EntrustmentProjectCompanyDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		//过滤草稿项目
		entrustmentProjectItemMapper.queryProjectListByCompId(compId);
		return SmartResult.ofPage(page);
	}

	public SmartResult<ProjectEntrusteeInfoDto> listProjectEntrustmentInfo(BaseSimpleFormBean<Integer> formBean) {
		Integer importId = formBean.getReqdata();
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(importId);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);

		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(importId);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);

		/*
		ProjectEntrustmentInfoDto info = new ProjectEntrustmentInfoDto().setImportId(importId)
				.setCompid(entrustmentProject.getCompid())
				.setCompname(entrustmentProject.getCompname());

		MakerAlipayPrincipal makerAlipayPrincipal = new MakerAlipayPrincipal().selectById(entrustmentProject.getPrincipalId());
		if (makerAlipayPrincipal != null) {
			info.setPrincipalId(entrustmentProject.getPrincipalId()).setPrincipalName(makerAlipayPrincipal.getName());
		}*/

		List<ProjectEntrusteeInfoDto> entrusteeList = getEntrusteeList(itemList);
		return SmartResult.success(entrusteeList);
	}

	private List<ProjectEntrusteeInfoDto> getEntrusteeList(List<EntrustmentProjectItemDto> itemList) {
		return itemList.stream().collect(Collectors.groupingBy(EntrustmentProjectItemDto::getEntrusteeId)).values().stream().map(list -> {
			ProjectEntrusteeInfoDto entrustee = list.stream()
					.map(ProjectEntrusteeInfoDto::of)
					.reduce(ProjectEntrusteeInfoDto::add)
					.orElse(new ProjectEntrusteeInfoDto());
			entrustee.setItemList(list);
			return entrustee;
		}).collect(Collectors.toList());
	}

	public void downloadProjectEntrusteeContractZipFile(HttpServletResponse response, int projectid) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(projectid);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);
		// 只有已完成的委托项目才能导出
		Asserts.isTrue(NumberUtil.equals(entrustmentProject.getState(), EntrustProjectImportState.FULL_COMPLETE), StatusMsg.StatusMsg_1111);

		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(projectid);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);

		List<ProjectEntrusteeInfoDto> entrusteeList = getEntrusteeList(itemList);
		docService.downloadProjectEntrusteeContractZipFile(response, entrustmentProject, entrusteeList);
	}
	public void zddDownloadProjectEntrusteeContractZipFile(HttpServletResponse response, int projectid) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(projectid);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);
		// 只有已完成的委托项目才能导出
		Asserts.isTrue(NumberUtil.equals(entrustmentProject.getState(), EntrustProjectImportState.FULL_COMPLETE), StatusMsg.StatusMsg_1111);
		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(projectid);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);
		List<ProjectEntrusteeInfoDto> entrusteeList = getEntrusteeList(itemList);
		docService.zddDownloadProjectEntrusteeContractZipFile(response, entrustmentProject, entrusteeList);
	}
	public void downloadProjectEntrusteeContractFile(HttpServletResponse response, int projectid, int entrusteeId) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(projectid);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);

		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(projectid);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);

		ProjectEntrusteeInfoDto infoDto = getEntrusteeList(itemList).stream()
				.filter(item -> NumberUtil.equals(item.getEntrusteeId(), entrusteeId))
				.findFirst()
				.orElse(null);
		Asserts.notNull(infoDto, StatusMsg.StatusMsg_1110);

		docService.downloadProjectEntrusteeContractFile(response, entrustmentProject, infoDto);
	}
	/**
	 * 按月获取企业历史委托接单列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult<EntrustmentProjectCompanyDto> monthlyQueryCompanyHistoryProjects(BaseSimpleFormBean<MonthlyQueryCompanyHistoryProjectsFormBean> formBean) {
		MonthlyQueryCompanyHistoryProjectsFormBean reqdata = formBean.getReqdata();
		int year = reqdata.getYear();
		int month = reqdata.getMonth();
		Integer compId = reqdata.getCompId();
		Asserts.notNull(reqdata.getCompId(), StatusMsg.StatusMsg_133);
		Page<EntrustmentProjectCompanyDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		entrustmentProjectItemMapper.monthlyQueryCompanyHistoryProjects(compId,year,month);
		return SmartResult.ofPage(page);
	}

	public void downloadEreceiptZipFile(HttpServletResponse response, int projectId) {
		coreMakerAlipayService.downloadEreceiptZipFile(response, projectId);
	}

	public void downloadTheCommissionMakerContractPdf(HttpServletResponse response, int projectid, int entrusteeId) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(projectid);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);

		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(projectid);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);

		ProjectEntrusteeInfoDto infoDto = getEntrusteeList(itemList).stream()
				.filter(item -> NumberUtil.equals(item.getEntrusteeId(), entrusteeId))
				.findFirst()
				.orElse(null);
		Asserts.notNull(infoDto, StatusMsg.StatusMsg_1110);

		docService.downloadProjectEntrusteContractPDF(response, entrustmentProject, infoDto);
	}

	public void downloadProjectMakerContractZipPDF(HttpServletResponse response, int projectid) {
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(projectid);
		Asserts.notNull(entrustmentProject, StatusMsg.StatusMSG_1101);
		// 只有已完成的委托项目才能导出
		Asserts.isTrue(NumberUtil.equals(entrustmentProject.getState(), EntrustProjectImportState.FULL_COMPLETE), StatusMsg.StatusMsg_1111);

		List<EntrustmentProjectItemDto> itemList = entrustmentProjectItemMapper.listByImportId(projectid);
		Asserts.notEmpty(itemList, StatusMsg.StatusMSG_1101);

		List<ProjectEntrusteeInfoDto> entrusteeList = getEntrusteeList(itemList);
		docService.downloadProjectEntrusteeContractZipPDF(response, entrustmentProject, entrusteeList);
	}

	/**
	 * 委托接单发相同单检测 15分钟内发给同一个人相同金额的返回错误提示
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult checkSameProject(BaseSimpleFormBean<CheckSameProjectFormBean> formBean) {
		CheckSameProjectFormBean reqdata = formBean.getReqdata();
		List<Integer> projectIds = reqdata.getProjectIds();

		List<SameProjectDto> same = coreProjectService.getTimeSameEntTradeAmount(StringUtils.join(projectIds, ","));
		return SmartResult.success(same);
	}

	public SmartResult uploadProjectFileUrl(BaseSimpleFormBean<UploadProjectFileUrlFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata() || org.springframework.util.CollectionUtils.isEmpty(formBean.getReqdata().getProjectIds())) {
			return SmartResult.ofEmptyData();
		}
		UploadProjectFileUrlFormBean reqdata = formBean.getReqdata();
		//项目信息
		List<EntrustmentProject> projectList = new EntrustmentProject().selectList(Condition.create().in("id", reqdata.getProjectIds()));
		if (CollectionUtils.isEmpty(projectList)) {
			return SmartResult.fail(StatusMsg.StatusMsg_301);
		}
		for (EntrustmentProject entrustmentProject : projectList) {
			entrustmentProject.setAttachmentUrl(reqdata.getProjectFileUrl());
			if (!entrustmentProject.updateById()) {
				return SmartResult.fail(StatusMsg.StatusMsg_199);
			}
		}
		return SmartResult.success();
	}

	public  void generalEntrustDeliveryProject(){
		List<EntrustmentProjectItemReduceDto> zddIds = entrustmentProjectItemMapper.getCompProjectDeliveryNum(0,ProjectType.ENTRUST_ZHIDUODUO);
		List<EntrustmentProjectItemReduceDto> croIds = entrustmentProjectItemMapper.getCompProjectDeliveryNum(0,ProjectType.ENTRUST_CROWDSOURCE);
		if(!CollectionUtils.isEmpty(zddIds)){
			log.info("自动生成委托 项目验收单开始,ID：" + zddIds.toString());
			docService.generateEntrustZddProjectDocDeliverFile(0, zddIds);
		}
		if(!CollectionUtils.isEmpty(croIds)){
			log.info("自动生成委托智众包项目验收单开始,ID：" + croIds.toString());
			docService.generateEntrustCroProjectDocDeliverFile(0, croIds, 3);
		}

	}
}
